package com.selune.online.ordering.system.project.tenant.service;


import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Throwables;
import static com.selune.online.ordering.system.common.util.IdUtils.goodsGenId;
import com.selune.online.ordering.system.project.api.base.entity.GoodsInfo;
import com.selune.online.ordering.system.project.api.base.exception.GoodsException;
import com.selune.online.ordering.system.project.api.base.response.Response;
import com.selune.online.ordering.system.project.api.mapper.GoodsInfoMapper;
import com.selune.online.ordering.system.project.api.pojo.goods.dto.GoodsDTO;
import com.selune.online.ordering.system.project.api.pojo.goods.dto.GoodsSearchDTO;
import com.selune.online.ordering.system.project.api.pojo.goods.dto.GoodsUpdateDTO;
import com.selune.online.ordering.system.project.api.pojo.goods.vo.GoodsDetailVO;
import com.selune.online.ordering.system.project.api.service.tenant.ITenantGoodsService;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 商户端商品管理Service
 *
 * @author xiaoyp
 * @date 2020/2/27
 */

@Service
@Slf4j
public class TenantGoodsServiceImpl implements ITenantGoodsService {
	
	@Resource
	private GoodsInfoMapper goodsInfoMapper;
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Response<Boolean> saveGoods(GoodsDTO goodsDTO) {
		if (null == goodsDTO || StringUtils.isBlank(goodsDTO.getGoodsName())
				|| null == goodsDTO.getGoodsPrice() || null == goodsDTO.getGoodsStock()) {
			log.error("ACCESS_LOG[]TenantGoodsServiceImpl[]saveGoods[]goodsDTO or goods_name or goods_price goods_stock is null!");
			return Response.error("goods.is.null");
		}
		goodsDTO.setGoodsId(goodsGenId());
		GoodsInfo goodsInfo = new GoodsInfo();
		
		BeanUtils.copyProperties(goodsDTO, goodsInfo);
		goodsInfo.setId(goodsInfo.getGoodsId());
		goodsInfo.setGoodsStatus(0);
		
		int result = goodsInfoMapper.insert(goodsInfo);
		if (result == 1) {
			return Response.success("添加商品成功!", Boolean.TRUE);
		} else {
			return Response.error("添加商品失败");
		}
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Response<Boolean> updateGoods(Long goodsId, GoodsUpdateDTO goodsUpdateDTO) {
		GoodsInfo goodsInfo = getGoodsById(goodsId).getData();
		if (ObjectUtils.isEmpty(goodsInfo)) {
			log.error("ACCESS_LOG[]TenantGoodsServiceImpl[]updateGoods[]goods_id is not exist!");
			return Response.error("goods.is.not.exist");
		}
		
		if (StringUtils.isBlank(goodsUpdateDTO.getGoodsName()) || StringUtils.isBlank(goodsUpdateDTO.getGoodsPicture())
				|| null == goodsUpdateDTO.getCategoryType() || null == goodsUpdateDTO.getGoodsPrice()
				|| null == goodsUpdateDTO.getGoodsStock()) {
			log.error("ACCESS_LOG[]TenantGoodsServiceImpl[]updateGoods[]goods parameter is null!");
			return Response.error("goods.param.is.null");
		} else {
			goodsInfoMapper.update(new GoodsInfo().setGoodsName(goodsUpdateDTO.getGoodsName()),
					Wrappers.<GoodsInfo>lambdaUpdate()
							.set(GoodsInfo::getGoodsPicture, goodsUpdateDTO.getGoodsPicture())
							.set(GoodsInfo::getCategoryType, goodsUpdateDTO.getCategoryType())
							.set(GoodsInfo::getGoodsPrice, goodsUpdateDTO.getGoodsPrice())
							.set(GoodsInfo::getGoodsStock, goodsUpdateDTO.getGoodsStock())
							.set(GoodsInfo::getGoodsDescription, goodsUpdateDTO.getGoodsDescription())
							.eq(GoodsInfo::getGoodsId, goodsId));
			log.info("ACCESS_LOG[]TenantGoodsServiceImpl[]updateGoods[]update goods success!");
			return Response.success("更新商品成功!", Boolean.TRUE);
		}
	}
	
	@Override
	public Response<GoodsDetailVO> getGoodsDetail(Long goodsId) {
		GoodsInfo goodsInfo = getGoodsById(goodsId).getData();
		if (ObjectUtils.isEmpty(goodsInfo)) {
			log.error("ACCESS_LOG[]TenantGoodsServiceImpl[]getGoodsDetail[]goods_id is not exist!");
//			throw new GoodsException("goods.is.not.exist");
			return Response.error("goods.is.not.exist");
		}
		
		GoodsDetailVO goodsDetailVO = new GoodsDetailVO();
		
		BeanUtils.copyProperties(goodsInfo, goodsDetailVO);
		
		log.info("ACCESS_LOG[]TenantGoodsServiceImpl[]getGoodsDetail[]get goods detail success!");
		return Response.success(goodsDetailVO);
	}
	
	@Override
	public Response<Boolean> onSaleGoods(Long goodsId) {
		GoodsInfo goodsInfo = getGoodsById(goodsId).getData();
		if (ObjectUtils.isEmpty(goodsInfo)) {
			log.error("ACCESS_LOG[]TenantGoodsServiceImpl[]onSaleGoods[]goods_id is not exist!");
			return Response.error("goods.is.not.exist");
		}
		
		int result = goodsInfoMapper.onSaleGoods(goodsId);
		if (result == 1) {
			return Response.success("上架成功!", Boolean.TRUE);
		} else {
			return Response.error("上架失败");
		}
	}
	
	@Override
	public Response<Boolean> offSaleGoods(Long goodsId) {
		GoodsInfo goodsInfo = getGoodsById(goodsId).getData();
		if (ObjectUtils.isEmpty(goodsInfo)) {
			log.error("ACCESS_LOG[]TenantGoodsServiceImpl[]offSaleGoods[]goods_id is not exist!");
			return Response.error("goods.is.not.exist");
		}
		
		int result = goodsInfoMapper.offSaleGoods(goodsId);
		if (result == 1) {
			return Response.success("下架成功!", Boolean.TRUE);
		} else {
			return Response.error("下架失败!");
		}
	}
	
	@Override
	public Response<List<GoodsDetailVO>> listGoods(GoodsSearchDTO goodsSearchDTO) {
		List<GoodsInfo> goodsInfoList = goodsInfoMapper.listGoods(goodsSearchDTO);
		List<GoodsDetailVO> goodsDetailVOList = new ArrayList<>(goodsInfoList.size());
		goodsInfoList.forEach(goodsInfo -> {
			GoodsDetailVO goodsDetailVO = new GoodsDetailVO();
			BeanUtils.copyProperties(goodsInfo, goodsDetailVO);
			goodsDetailVOList.add(goodsDetailVO);
		});
		
		return Response.success(goodsDetailVOList);
	}
	
	@Override
	public Response<Page<GoodsDetailVO>> pageGoods(Integer current, Integer size,
	                                                GoodsSearchDTO goodsSearchDTO) {
		int newCurrent = null == current ? 1 : current;
		int pageSize = null == size ? 10 : size;
		Page<GoodsInfo> page = new Page<>(newCurrent, pageSize);
		Page<GoodsInfo> goodsInfoPage = goodsInfoMapper.selectPage(page, Wrappers.<GoodsInfo>lambdaQuery()
			.eq(ObjectUtils.isNotEmpty(goodsSearchDTO.getGoodsId()),
				GoodsInfo::getGoodsId, goodsSearchDTO.getGoodsId())
			.eq(ObjectUtils.isNotEmpty(goodsSearchDTO.getCategoryType()),
				GoodsInfo::getCategoryType, goodsSearchDTO.getCategoryType())
			.eq(ObjectUtils.isNotEmpty(goodsSearchDTO.getGoodsStatus()),
				GoodsInfo::getGoodsStatus, goodsSearchDTO.getGoodsStatus())
			.like(StringUtils.isNotBlank(goodsSearchDTO.getGoodsName()),
				GoodsInfo::getGoodsName, goodsSearchDTO.getGoodsName())
			.orderByAsc(GoodsInfo::getCategoryType));
		
		Page<GoodsDetailVO> goodsDetailVoPage = new Page<>();
		BeanUtils.copyProperties(goodsInfoPage, goodsDetailVoPage);
		
		return Response.success(goodsDetailVoPage);
	}
	
	private Response<GoodsInfo> getGoodsById(Long goodsId) {
		if (null == goodsId) {
			log.error("ACCESS_LOG[]TenantGoodsServiceImpl[]getGoodsById[]goods_id is null!");
			return Response.error("goods.id.is.null");
		}
		GoodsInfo goodsInfo;
		
		try {
			goodsInfo = goodsInfoMapper.findByGoodsId(goodsId);
		} catch (Exception e) {
			log.error("ACCESS_LOG[]TenantGoodsServiceImpl[]getGoodsById[]goods_id is not exist! cause:{}",
					Throwables.getStackTraceAsString(e));
			throw new GoodsException("goods.is.not.exist");
		}
		
		return Response.success(goodsInfo);
	}
	
}
